package nettyTest.server;

import com.zyc.remoting.dto.RpcRequest;
import com.zyc.remoting.dto.RpcResponse;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import nettyTest.coder.NettyKryoDecoderDemo;
import nettyTest.coder.NettyKryoEncoderDemo;
import nettyTest.serialize.KryoSerializerDemo;

/**
 * @author zyc
 * @create 2022--06--01 10:53
 */
public class NettyServerDemo {
    private final int port;

    public NettyServerDemo(int port) {
        this.port = port;
    }

    public void run() {
        //1.创建两个线程组 bossGroup和 workerGroup
        //2.bossGroup只是处理连接请求，真正的和客户端业务处理，会交给 workerGroup完成
        //3.两个都是无限循环
        //4. bossGroup和 workerGroup含有的子线程(NioEventLoop)的个数默认实际cpu核数*2
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        //序列化器
        KryoSerializerDemo kryoSerializer = new KryoSerializerDemo();

        //服务器启动类
        ServerBootstrap bootstrap = new ServerBootstrap();

        try {
            bootstrap.group(bossGroup, workerGroup) //设置两个线程组
                    .channel(NioServerSocketChannel.class) //服务器的通道实现
                    // TCP默认开启 Nagle 算法，该算法尽可能发送大的数据块，减少网络传输
                    // TCP_NODELAY参数控制是否启用此算法
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    // 开启TCP 底层心跳机制
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.SO_BACKLOG, 128) //设置线程队列等待连接个数
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() { //设置处理器
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 添加自定义编解码器
                            // 对于服务端需要对请求解码，响应编码
                            ch.pipeline().addLast(new NettyKryoDecoderDemo(kryoSerializer, RpcRequest.class));
                            ch.pipeline().addLast(new NettyKryoEncoderDemo(kryoSerializer, RpcResponse.class));

                            ch.pipeline().addLast(new NettyServerHandlerDemo());
                        }
                    });

            // 绑定端口，同步等待绑定成功
            ChannelFuture f = bootstrap.bind(port).sync();

            //对关闭通道进行监听
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
